package jingdong

import (
	"bytes"
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/base64"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
	"orderApi/express"
	"strings"
	"time"
)

func JdRoutesPost(appKey, appSecret, accessToken, body string) (benXiRoutes express.BenXiRoutes) {
	benXiRoutes.Status = true
	client := http.Client{}

	baseUri := "http://api.jdl.com"
	domain := "express"
	path := "/query/dynamictraceinfo"
	algorithm := "HMacSHA512"

	timestamp := time.Now().Format("2006-01-02 15:04:05")
	content := strings.Join([]string{
		appSecret,
		"access_token", accessToken,
		"app_key", appKey,
		"method", path,
		"param_json", body,
		"timestamp", timestamp,
		"v", "2.0",
		appSecret,
	}, "")
	sign, err := Sign(algorithm, []byte(content), appSecret)
	if err != nil {
		benXiRoutes.Status = false
		benXiRoutes.Message = fmt.Sprintf("%v", err)
		return benXiRoutes
	}

	uri := baseUri + path
	httpRequest, err := http.NewRequest("POST", uri, bytes.NewReader([]byte(body)))
	if err != nil {
		benXiRoutes.Status = false
		benXiRoutes.Message = fmt.Sprintf("%v", err)
		return benXiRoutes
	}

	query := httpRequest.URL.Query()
	query.Add("LOP-DN", domain)
	query.Add("app_key", appKey)
	query.Add("access_token", accessToken)
	query.Add("timestamp", timestamp)
	query.Add("v", "2.0")
	query.Add("sign", sign)
	query.Add("algorithm", algorithm)
	httpRequest.URL.RawQuery = query.Encode()

	// _, offset := time.Now().Zone()
	// httpRequest.Header.Add("lop-tz", fmt.Sprintf("%d", offset/3600))
	// httpRequest.Header.Add("User-Agent", "lop-http/go")

	httpResponse, err := client.Do(httpRequest)
	if err != nil {
		benXiRoutes.Status = false
		benXiRoutes.Message = fmt.Sprintf("%v", err)
		return benXiRoutes
	}

	b, err := ioutil.ReadAll(httpResponse.Body)
	if err != nil {
		benXiRoutes.Status = false
		benXiRoutes.Message = fmt.Sprintf("%v", err)
		return benXiRoutes
	}

	errs := new(ErrorResponse)
	json.Unmarshal(b, errs)

	if errs.ErrorResponse.Code != 0 {
		benXiRoutes.Status = false
		benXiRoutes.Message = string(b)
		return benXiRoutes
	}

	all := new(JdRoutes)
	json.Unmarshal(b, all)

	data, _ := xml.Marshal(all)
	xml.Unmarshal(data, &benXiRoutes)

	return benXiRoutes
}

// Sign 加密处理
func Sign(algorithm string, data []byte, secret string) (string, error) {
	if algorithm == "md5-salt" {
		h := md5.New()
		if _, err := h.Write(data); err != nil {
			return "", err
		}
		return fmt.Sprintf("%x", h.Sum(nil)), nil
	} else if algorithm == "HMacMD5" {
		h := hmac.New(md5.New, []byte(secret))
		if _, err := h.Write(data); err != nil {
			return "", err
		}
		return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
	} else if algorithm == "HMacSHA1" {
		h := hmac.New(sha1.New, []byte(secret))
		if _, err := h.Write(data); err != nil {
			return "", err
		}
		return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
	} else if algorithm == "HMacSHA256" {
		h := hmac.New(sha256.New, []byte(secret))
		if _, err := h.Write(data); err != nil {
			return "", err
		}
		return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
	} else if algorithm == "HMacSHA512" {
		h := hmac.New(sha512.New, []byte(secret))
		if _, err := h.Write(data); err != nil {
			return "", err
		}
		return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
	}
	return "", fmt.Errorf("algorithm %s not supported yet", algorithm)
}
